using System;
using System.Collections.Generic;
using System.Text;

using Mud.Common.Messages;
using Mud.Server.Users;
using Mud.Server.Physical;
using Mud.Common.Physical;
using Mud.Common;

namespace Mud.Server.Client.Commands
{

	/// <summary>
	/// Command which is created and executed when a client sends a command message to the server.
	/// </summary>
	[MessageHandler(MessageTypeIds.CommandGetServerInfo)]
	public sealed class CommandGetServerInfo : CommandBase
	{

		protected override IMessage ExecuteCommand(IServer server, IMessage commandData, IClient executor)
        {
			MessageResponseServerInfo message = new MessageResponseServerInfo();
			message.ServerLag = server.CurrentServerState.ServerLag;
			message.LastTickDuration = server.CurrentServerState.LastTickDuration;
			message.ClientCount = server.CurrentServerState.ClientCount;
			message.RemoteClientCount = server.CurrentServerState.RemoteClientCount;
			message.CommandMessagesProcessedLastTick = server.CurrentServerState.CommandMessagesProcessedLastTick;
			message.CommandMessagesProcessedTotal = server.CurrentServerState.CommandMessagesProcessedTotal;
			message.EventMessagesProcessedLastTick = server.CurrentServerState.EventMessagesProcessedLastTick;
			message.EventMessagesProcessedTotal = server.CurrentServerState.EventMessagesProcessedTotal;
			message.ServerStarted = server.CurrentServerState.ServerStarted;
			message.ServerName = server.CurrentConfiguration.ServerName;
			return message;
		}

	}

	/// <summary>
	/// Command which is executed when the client wants to broadcast the message to all other clients.
	/// </summary>
	[MessageHandler(MessageTypeIds.CommandServerBroadcast)]
	public sealed class CommandServerBroadcast : CommandBase
	{

		protected override IMessage ExecuteCommand(IServer server, IMessage commandData, IClient executor)
        {
            MessageCommandServerBroadcast command = 
                AssertIsMessage<MessageCommandServerBroadcast>(commandData, this);


			return WrapResult(server.BroadcastMessage(executor.User.UserName, command.Message));
		}

	}

	[MessageHandler(MessageTypeIds.CommandStopServer)]
	public sealed class CommandStopServer : CommandBase
	{

		protected override IMessage ExecuteCommand(IServer server, IMessage commandData, IClient executor)
        {
			server.ServerStopFlag.SetFlag(true);
            return MessageResponseOk.Instance;
		}

	}

    [MessageHandler(MessageTypeIds.CommandLogout)]
	public sealed class CommandLogout : CommandBase
    {

		protected override IMessage ExecuteCommand(IServer server, IMessage commandData, IClient executor)
        {
			ResultWithReason response;
            if (executor.CreatureControler.ControledCreature != null)
            {
                response = server.ExitGame(executor.CreatureControler.ControledCreature);
				if (!response.Success)
					return WrapResult(response);
            }
            executor.DisconnectClient();
            return MessageResponseOk.Instance;
        }

    }

    [MessageHandler(MessageTypeIds.CommandGetPlayerCharacters)]
	public sealed class CommandGetPlayerCharacters : CommandBase
    {

		protected override IMessage ExecuteCommand(IServer server, IMessage commandData, IClient executor)
        {
            User user = executor.User;
			IList<Creature> creatures = server.CurrentObjectLoader.GetPlayerCharacters(user);
            MessageResponseGetPlayerCharacters msg = new MessageResponseGetPlayerCharacters();
            foreach (Creature creature in creatures)
                msg.Characters.Add(ObjectToMessageMapper.MapToMessage(creature, creature));

            return msg;
        }

    }


    [MessageHandler(MessageTypeIds.CommandPlay)]
	public sealed class CommandPlay : CommandBase
    {

		protected override IMessage ExecuteCommand(IServer server, IMessage commandData, IClient executor)
        {
            MessageCommandPlay command = AssertIsMessage<MessageCommandPlay>(commandData, this);
            User user = executor.User;
			IList<Creature> creatures = server.CurrentObjectLoader.GetPlayerCharacters(user);
            Creature selectedCreature = null;
            foreach (Creature creature in creatures)
            {
                if (creature.Name == command.CharacterName)
                {
                    selectedCreature = creature;
                    break;
                } 
            }
            if (selectedCreature == null)
                return new MessageResponseError("No character with name " + command.CharacterName);

            selectedCreature.AttachControler(executor.CreatureControler);
            ResultWithReason response =  server.EnterGame(selectedCreature, selectedCreature.CurrentAreaName);
			if (!response.Success)
				return WrapResult(response);

			MessageResponsePlay responseMessage = new MessageResponsePlay();
			responseMessage.PlayerCharacter = ObjectToMessageMapper.MapToMessage(selectedCreature, selectedCreature);
			return responseMessage;
        }

    }

}
